<?php

Raise::load('core.RaiseStaticClass');
Raise::load('core.RaiseFile');
Raise::load('core.RaiseGzipFileStream');
Raise::load('core.RaiseConvert');

/**
 * Check whether Zlib is enabled or not
 */
if (function_exists('gzopen')) {

    /**
     * RaiseGzip class
     * Provides Gzip compression support using the Zlib extension
     *
     * @link http://php.net/zlib
     * @author Sam-Mauris Yong <hellclanner at live dot com>
     * @license http://www.opensource.org/licenses/bsd-license New BSD License
     * @package Raise.Core.IO.Compression
     * @since 1.2
     */
    class RaiseGzip extends RaiseStaticClass {
        const GZIP = 'gzip';
        const BZIP2 = 'bzip2';

        /**
         * GZip encode the content and write it to a file.
         * If file exists, the file will be replaced.
         * @param RaiseFile $file The pathname to write the Gzipped content to
         * @param string $content The content to be Gzipped
         * @param int $level (optional) The level of compression (-1 to 9) Default is -1 (automatic)
         * @static
         */
        public static function write($file, $content, $level = -1) {
            if ($file instanceof RaiseFile) {
                $file = $file->getPathName();
            }
            $stream = new RaiseGzipFileStream($file, $level);
            $stream->write($content);
            $stream->close();
        }

        /**
         * Append the content, then Gzip encode and write it back to the file
         * @param RaiseFile $file  The pathname to write the Gzipped content to
         * @param string $content  The content to be appended and Gzipped
         * @param int $level (optional) The level of compression (-1 to 9) Default is -1 (automatic)
         * @static
         */
        public static function append($file, $content, $level = -1) {
            if ($file->exists()) {
                $content = self::get($file) . $content;
            }
            self::write($file, $content, $level);
        }

        /**
         * Get all the content of a Gzip encoded file
         * @param RaiseFile $file The pathname to get all Gzip encoded content
         * @return string The content of the Gzip file
         * @link http://php.net/gzfile
         * @static
         */
        public static function get($file) {
            if ($file instanceof RaiseFile) {
                $file = $file->getPathName();
            }
            $data = gzfile($file);
            $data = implode($data);
            return $data;
        }

        /**
         * Compress a file with GZIP method to another file
         * @param RaiseFile $input The file to compress
         * @param RaiseFile $output  The destination of the compressed file
         * @static
         */
        public static function compressFile($input, $output) {
            if (!($input instanceof RaiseFile)) {
                $input = new RaiseFile($input);
            }
            if (!($output instanceof RaiseFile)) {
                $output = new RaiseFile($output);
            }
            $output->setContent(self::compress($input->getContent()));
            $input->close();
            $output->close();
        }

        /**
         * Uncompress a file that has been previously compressed with GZIP method to another file
         * @param RaiseFile $input The compressed file
         * @param RaiseFile $output The destination of the decompessed file
         * @static
         */
        public static function uncompressFile($input, $output) {
            if (!($input instanceof RaiseFile)) {
                $input = new RaiseFile($input);
            }
            if (!($output instanceof RaiseFile)) {
                $output = new RaiseFile($output);
            }
            $output->setContent(self::uncompress($input->getContent()));
            $input->close();
            $output->close();
        }

        /**
         * Compress a file with DEFLATE algorithm to another file
         * @param RaiseFile $input The file to compress
         * @param RaiseFile $output  The destination of the compressed file
         * @static
         */
        public static function deflateFile($input, $output) {
            if (!($input instanceof RaiseFile)) {
                $input = new RaiseFile($input);
            }
            if (!($output instanceof RaiseFile)) {
                $output = new RaiseFile($output);
            }
            $output->setContent(self::deflate($input->getContent()));
            $input->close();
            $output->close();
        }

        /**
         * Uncompress a file that has been previously compressed with DEFLATE algorithm to another file
         * @param string $input The deflated file
         * @param string $output The destination of the inflated file
         * @static
         */
        public static function inflateFile($input, $output) {
            if (!($input instanceof RaiseFile)) {
                $input = new RaiseFile($input);
            }
            if (!($output instanceof RaiseFile)) {
                $output = new RaiseFile($output);
            }
            $output->setContent(self::inflate($input->getContent()));
            $input->close();
            $output->close();
        }

        /**
         * Get the file compression type by reading the first few bytes of the file
         * @param RaiseFile $input The file to get the file compression type
         * @return string Return one of the constants from RaiseGzip, or 'unknown' for file type not known
         * @static
         */
        public static function getFileCompressionType($input) {
            if (!($input instanceof RaiseFile)) {
                $input = new RaiseFile($input);
            }
            $stream = $input->getStream();
            $type = $stream->read(3);
            $stream->close();
            if (RaiseConvert::binaryToHexadecimal(substr($type, 0, 2)) == '789c') {
                return self::GZIP;
            } elseif ($type == 'BZh') {
                return self::BZIP2;
            }
            return 'unknown';
        }

        /**
         * Compress a string using DEFLATE algorithm
         * @param string $str The string to compress
         * @param int $level (optional) The level of compression (-1 to 9) Default is -1 (automatic)
         * @return string The compressed string
         * @link http://php.net/gzdeflate
         */
        public static function deflate($str, $level = -1) {
            return gzdeflate($str, $level);
        }

        /**
         * Uncompress a string that has been previously compressed using DEFLATE algorithm
         * @param string $str The string to uncompress
         * @return string The uncompressed string
         * @link http://php.net/gzinflate
         * @static
         */
        public static function inflate($str) {
            return gzinflate($str);
        }

        /**
         * Compress a string using GZIP method
         * @param string $str The string to compress
         * @param int $level (optional) The level of compression (-1 to 9) Default is -1 (automatic)
         * @return string
         * @link http://php.net/gzcompress
         * @static
         */
        public static function compress($str, $level = -1) {
            return gzcompress($str, $level);
        }

        /**
         * Uncompress a string that has been previously compressed using GZIP method
         * @param string $str The compressed string
         * @return string The uncompressed string
         * @link http://php.net/gzuncompress
         * @static
         */
        public static function uncompress($str) {
            return gzuncompress($str);
        }

    }

}